from copy import deepcopy

from django.db import models

from .filters import JsonFieldFilter, DateFilter
from django_filters.rest_framework import filterset as rest_filterset

FILTER_FOR_DBFIELD_DEFAULTS = deepcopy(rest_filterset.FILTER_FOR_DBFIELD_DEFAULTS)
FILTER_FOR_DBFIELD_DEFAULTS.update({
    models.JSONField: {'filter_class': JsonFieldFilter},
    models.DateTimeField: {'filter_class': DateFilter},
    models.DateField: {'filter_class': DateFilter},
    models.TimeField: {'filter_class': DateFilter}
})


class FilterSet(rest_filterset.FilterSet):
    FILTER_DEFAULTS = FILTER_FOR_DBFIELD_DEFAULTS
    
    def __init__(self, *args, **kwargs):
        super(FilterSet, self).__init__(*args, **kwargs)

    def filter_queryset(self, queryset):
        """
        Filter the queryset with the underlying form's `cleaned_data`. You must
        call `is_valid()` or `errors` before calling this method.

        This method should be overridden if additional filtering needs to be
        applied to the queryset before it is cached.
        """
        for name, value in self.form.cleaned_data.items():
            queryset = self.filters[name].filter(queryset, value)
            assert isinstance(queryset, models.QuerySet), \
                "Expected '%s.%s' to return a QuerySet, but got a %s instead." \
                % (type(self).__name__, name, type(queryset).__name__)
        return queryset

    @staticmethod
    def get_filter_name(field_name, lookup_expr):
        return field_name